package com.sogoodsoft.core.action;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import com.sogoodsoft.core.service.EntityService;
import com.sogoodsoft.core.support.Page;
import com.sogoodsoft.core.support.UserParam;

/**
 * Action基类
 * 
 */
/**
 * @author zhaisk
 * 
 * @param <T>
 * @param <PK>
 */
public abstract class BaseAction<T, PK extends Serializable> extends ActionSupport
        implements Preparable, ModelDriven < Object >, ServletRequestAware, ServletResponseAware {

    /**
	 * 
	 */
    private final static long serialVersionUID = 1L;

    protected final Log logger = LogFactory.getLog(getClass()); // 为子类定义的logger

    protected T entity; // 模型对象

    protected List < T > entites; // 模型对象列表

    protected Class < T > entityClass; // 模型对象对象类

    protected String entityClassName; // 模型对象对象类名

    protected Page page; // 分页对象

    protected Map mapRef; // 页面关联Map

    protected Map listRef; // 页面关联List ,

    protected HttpServletRequest request;

    protected HttpServletResponse response;

    protected Object parentId;

    protected String menuId;

    protected String keywords;

    /**
     * 
     */
    protected String orderBy;

    /**
     * 
     */
    protected String isAsc;

    protected Long currentPageSize;

    protected UserParam userParam; // 个性化用户设置参数

    // public static final String LIST = "list"; // list页面定义
    // public static final String VIEW = "view"; // view页面定义
    public final static String SAVE = "save"; // view页面定义

    public final static String DELETE = "delete";

    public final static String DELETEBULK = "deleteBulk";

    // 重复字段验证
    public String ventityName = ""; // 实体名称

    public String vid = ""; // 实体ID

    public String validateValue; // 验证参数

    public String validateError; // ajax

    public String validateId; // 字段

    public BaseAction() {
        super();
        // 通过反射获取entity的class
        entityClass = (Class < T >) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        entityClassName = entityClass.getSimpleName();

        // 构造分页对象
        if (userParam != null && StringUtils.isNotEmpty(userParam.getPageNum())) {
            page = new Page(Integer.parseInt(userParam.getPageNum()));
        } else {
            page = new Page();
        }
    }

    /**
     * @see ModelDriven
     */
    @Override
    public T getModel() {
        return entity;
    }

    /**
     * 向页面返回对象列表
     */
    public List < T > getEntites() {
        return entites;
    }

    /**
     * 缺省执行函数,显示对象列表
     */
    @Override
    public String execute() throws Exception {
        return list();
    }

    /**
     * 显示对象列表页
     */
    @SuppressWarnings("unchecked")
    public String list() throws Exception {
        // page = getService().findPaged(entity, page.getPageNo(), page.getPageSize());
        String torderBy = StringUtils.isNotEmpty(userParam.getSorting()) ? userParam.getSorting() : null;
        torderBy = StringUtils.isNotEmpty(orderBy) ? orderBy : torderBy;
        boolean tisAsc = userParam.isAsc();

        if (StringUtils.isNotEmpty(isAsc)) {
            tisAsc = isAsc.equals("true") ? true : false;
        }
        page.setPageSize(StringUtils.isNotEmpty(userParam.getPageNum()) ? Integer.parseInt(userParam.getPageNum())
                : page.getPageSize());
        page = getService().findPaged(entity, page.getPageNo(), page.getPageSize(), torderBy, tisAsc);
        entites = (List < T >) page.getResult();
        onDisplayPrepare();
        return SUCCESS;
    }

    /**
     * 显示对象查看页
     */
    public String view() throws Exception {
        onDisplayPrepare();
        return SUCCESS;
    }

    /**
     * 显示新增或修改页
     */
    @Override
    public String input() throws Exception {
        onDisplayPrepare();
        return SUCCESS;
    }

    /**
     * 删除对象
     */
    @SuppressWarnings("unchecked")
    public String delete() throws Exception {
        PK id = (PK) getId();
        if (StringUtils.isNotEmpty((String) id)) {
            getService().delete(id);
        }
        return DELETE;
    }

    /**
     * 新增或修改对象保存
     */
    @SuppressWarnings("unchecked")
    public String save() throws Exception {
        PK id = (PK) getId();
        if (StringUtils.isEmpty((String) id)) {
            getService().save(entity);
        } else {
            getService().update(entity);
        }
        return SAVE;
    }

    /**
     * 批量删除对象
     */
    @SuppressWarnings("unchecked")
    public String deleteBulk() throws Exception {
        Object[] ids = getIds();
        if (ids != null && ids.length > 0) {
            for (int i = 0; i < ids.length; i++) {
                getService().delete((PK) ids[i]);
            }
        }
        return DELETEBULK;
    }

    /**
     * @see Preparable
     */
    @Override
    @SuppressWarnings("unchecked")
    public void prepare() throws Exception {
        PK id = (PK) getId();
        if (StringUtils.isNotEmpty((String) id)) {
            entity = getService().load(id);
        } else {
            entity = entityClass.newInstance();
        }
        onPrepare();
    }

    /**
     * 获取Manager,子类必须实现
     */
    protected abstract EntityService < T, PK > getService();

    /**
     * 获取主键id,子类必须实现
     */
    protected abstract Object getId();

    /**
     * 获取主键id数组,子类必须实现
     */
    protected abstract Object[] getIds();

    /**
     * @see #prepare()
     */
    protected void onPrepare() throws Exception {
        // 可在子类中重载,在prepare()中调用.
    }

    /**
     * @see #list()
     * @see #input()
     */
    protected void onDisplayPrepare() throws Exception {
        // 可在子类中重载.准备显示页面需要的辅助对象,在list(),input()中调用.
    }

    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }

    @Override
    public void setServletResponse(HttpServletResponse response) {
        this.response = response;
    }

    public Map getMapRef() {
        return mapRef;
    }

    public Map getListRef() {
        return listRef;
    }

    public Page getPage() {
        return page;
    }

    public void setPage(Page page) {
        this.page = page;
    }

    /**
     * 将集合转换成Map
     */
    public Map populateMap(Collection collection, String keyProperty, String valueProperty) {
        HashMap map = new HashMap();
        Iterator it = collection.iterator();
        while (it.hasNext()) {
            Object entity = it.next();
            Object key = null;
            Object value = null;
            try {
                key = PropertyUtils.getProperty(entity, keyProperty);
                value = PropertyUtils.getProperty(entity, valueProperty);
                map.put(key, value);
            } catch (Exception e) {
            }
        }
        return map;
    }

    public void repeatValidation() throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(
            String.valueOf(getService().repeatValidation(validateId, validateValue, validateError, ventityName, vid)));
    }

    public String getVentityName() {
        return ventityName;
    }

    public String getVid() {
        return vid;
    }

    public void setVentityName(String ventityName) {
        this.ventityName = ventityName;
    }

    public void setVid(String vid) {
        this.vid = vid;
    }

    public String getValidateValue() {
        return validateValue;
    }

    public String getValidateError() {
        return validateError;
    }

    public void setValidateValue(String validateValue) {
        this.validateValue = validateValue;
    }

    public void setValidateError(String validateError) {
        this.validateError = validateError;
    }

    public String getValidateId() {
        return validateId;
    }

    public void setValidateId(String validateId) {
        this.validateId = validateId;
    }

    public UserParam getUserParam() {
        return userParam;
    }

    public void setUserParam(UserParam userParam) {
        this.userParam = userParam;
    }

    public String getOrderBy() {
        return orderBy;
    }

    public Long getCurrentPageSize() {
        return currentPageSize;
    }

    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }

    public void setCurrentPageSize(Long currentPageSize) {
        this.currentPageSize = currentPageSize;
    }

    public String getMenuId() {
        return menuId;
    }

    public void setMenuId(String menuId) {
        this.menuId = menuId;
    }

    public String getIsAsc() {
        return isAsc;
    }

    public void setIsAsc(String isAsc) {
        this.isAsc = isAsc;
    }

    public String getKeywords() {
        return keywords;
    }

    public void setKeywords(String keywords) {
        this.keywords = keywords;
    }
}
